/**************************************************************************
*   Copyright (C) 2009 Chernov Dmitry                                     *
*   diman4ik.chernov@gmail.com                                            *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/

#include "korners_game_engine_network.h"
#include "korners_protocol.h"
#include "korners_socket.h"
#include "korners_server.h"

#include <KDebug>
#include <KLocale>


KornersGameEngineNetwork::KornersGameEngineNetwork( const QString& netName, 
                                                    bool server, 
                                                    int port, 
                                                    const QString& peerIp)
{
    m_nickName = netName;
    m_server = 0;

    m_curGameProto = new KornersGameProtocol(netName, server);

    connect( m_curGameProto, SIGNAL( messageParsed( KornersMessage ) ), 
             SLOT( messageReceived( KornersMessage ) ) );

    m_socket = new KornersSocket( m_curGameProto, this );

    if( server )
    {
        m_server = new KornersServer( m_socket, this );
        m_server->startListen(port);
        connect( m_server, SIGNAL( newConnection() ), SLOT( incomingConnection() ) );
    }
    else
    {
        m_socket->connectTo( peerIp, port );
        connect( m_socket, SIGNAL( connectionFailed() ), SLOT( connectionFailed() ) );
    }

    connect( m_socket, SIGNAL( disconnected() ), SLOT( onDisconnect() ) );
}

KornersGameEngineNetwork::~KornersGameEngineNetwork()
{
    const QByteArray& msg = m_curGameProto->stop();
    m_socket->send(msg);
    m_socket->close();
    if( m_server != 0 )
        m_server->close();
}

void KornersGameEngineNetwork::makeNextMove( const QPoint& src, const QPoint& dst )
{
    const QByteArray& msg  = m_curGameProto->move(src, dst);
    m_socket->send(msg);
}

void KornersGameEngineNetwork::messageReceived( KornersMessage mess )
{
    switch(mess.type)
    {
        case KornersMessage::handshake_s:
            {
                m_peerName = mess.data.front().toString();
                emit( engineMessage( m_peerName + i18n(" connected") ) );
                emit( opponentName(m_peerName) );
                const QByteArray& msg = m_curGameProto->start();
                m_socket->send(msg);
            }
            break;
        case KornersMessage::handshake_c:
            {
                m_peerName = mess.data.front().toString();
                emit( engineMessage( m_peerName + i18n(" connected") ) );
                emit( opponentName(m_peerName) );
            }
            break;
        case KornersMessage::move:
            {
                // Rotate the board
                QPoint src = rotatePoint( mess.data[0].toPoint() );
                QPoint dst = rotatePoint( mess.data[1].toPoint() );
                computerMove( src, dst );
            }
            break;
        case KornersMessage::regret:
            emit( engineMessage( m_peerName + i18n(" gives up") ) );
            break;
        default:
            break;
    }
}

void KornersGameEngineNetwork::incomingConnection()
{
    kDebug() << "connected";

    const QByteArray& msg = m_curGameProto->start();
    m_socket->send(msg);
    emit( canPlay() );
}

void KornersGameEngineNetwork::connectionFailed()
{
    emit( engineMessage( i18n("Connection failed") ) );
}

void KornersGameEngineNetwork::onDisconnect()
{
    emit( engineMessage( i18n("Connection lost") ) );
}

bool KornersGameEngineNetwork::canSelect( const QPoint& src ) const
{
    if( m_field[ pointToIndex(src) ] == player )
	return true;
    return false;
}

bool KornersGameEngineNetwork::canMove( QPoint src, QPoint dst ) const
{
    if( isMoveValid( src, dst, player ) )
	return true;
    return false;
}
